package com.ict.ms.controller;


import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.ict.ms.abnormal.facade.api.IAbnormalService;
import com.ict.ms.abnormal.facade.common.SplitUtils;
import com.ict.ms.abnormal.facade.dto.AreaSet;
import com.ict.ms.targetLocation.facade.common.PageUtils;
import com.ict.ms.area.facade.api.IAreaAddService;
import com.ict.ms.area.facade.api.IAreaOpeService;
import com.ict.ms.area.facade.dto.CircularGeoDto;
import com.ict.ms.area.facade.dto.GeoDto;
import com.ict.ms.area.facade.dto.SectorGeoDto;
import com.ict.ms.area.facade.model.Area;
import com.ict.ms.area.facade.model.Point;
import com.ict.ms.common.StateMsg;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by StevenH on 2016/12/15.
 */
@Controller
@RequestMapping("/area")
public class AreaController {
    @Resource
    IAreaAddService addService;
    @Resource
    IAreaOpeService opeService;
    @Resource
    IAbnormalService abnormalService;

    /**
     * 添加矩形区域
     *
     * @param map   略
     * @param ldlon 左下
     * @param ldlat 左下
     * @param rulon 右上
     * @param rulat 右上
     * @param name  区域名
     * @param user  创建者
     * @param type  添加区域类型：0：异常监控敏感区域；1：分发区域；2：其他区域（待定义）
     * @return 区域被添加时id
     */
    @ResponseBody
    @RequestMapping(value = "addrec.do", method = RequestMethod.POST)
    public String addRectangle(ModelMap map, @RequestParam(value = "ldlon", required = false) double ldlon,
                               @RequestParam(value = "ldlat", required = false) double ldlat,
                               @RequestParam(value = "rulon", required = false) double rulon,
                               @RequestParam(value = "rulat", required = false) double rulat,
                               @RequestParam(value = "name", required = false) String name,
                               @RequestParam(value = "user", required = false) String user,
                               @RequestParam(value = "type", required = false) int type) {
        Point p1 = new Point(ldlon, ldlat);
        Point p2 = new Point(rulon, rulat);
        int id = addService.addRectangle(p1, p2, name, user, type);
        if (id < 0) {
            map.addAttribute("error", "创建失败");
            return StateMsg.toJson(id, map);
        }
        //300表示只存在自定义区域，id无用
        if (type == 300) {
            id = 0;
        }
        map.addAttribute("id", id);
        return StateMsg.toJson(1, map);
    }

    private int addRectangle(double ldlon, double ldlat, double rulon, double rulat, String name, String user, int type) {
        Point p1 = new Point(ldlon, ldlat);
        Point p2 = new Point(rulon, rulat);
        return addService.addRectangle(p1, p2, name, user, type);
    }

    /**
     * 添加多边形
     *
     * @param map    略
     * @param points 点集合，坐标内之间用下划线“_”分割，坐标间用“~”分割，不需要闭环
     *               eg:"1.1_1.1~1.1_2.2~2.2_2.2~2.2_1.1"
     * @param name   同上
     * @param user   同上
     * @param type   同上
     * @return 同上
     */
    @ResponseBody
    @RequestMapping(value = "addpol2.do", method = RequestMethod.POST)
    public String addPolygon(ModelMap map, @RequestParam(value = "points") String points,
                             @RequestParam(value = "name", required = false) String name,
                             @RequestParam(value = "user", required = false) String user,
                             @RequestParam(value = "type", required = false) int type) {
        String[] pointStr = points.split("~");
        int length = pointStr.length;
        Point[] pointArr = new Point[length];
        int i = 0;
        for (String one : pointStr) {
            Point point = new Point(Double.parseDouble(one.split("_")[0]), Double.parseDouble(one.split("_")[1]));
            pointArr[i++] = point;
        }

        int id = addService.addPolygon(pointArr, name, user, type);
        if (id < 0) {
            map.addAttribute("error", "创建失败");
            return StateMsg.toJson(id, map);
        }
        //300表示只存在自定义区域，id无用
        if (type == 300) {
            id = 0;
        }
        map.addAttribute("id", id);
        return StateMsg.toJson(1, map);
    }

    private int addPolygon(String points, String name, String user, int type) {
        String[] pointStr = points.split("~");
        int length = pointStr.length;
        Point[] pointArr = new Point[length];
        int i = 0;
        for (String one : pointStr) {
            Point point = new Point(Double.parseDouble(one.split("_")[0]), Double.parseDouble(one.split("_")[1]));
            pointArr[i++] = point;
        }

        return addService.addPolygon(pointArr, name, user, type);
    }

    /**
     * 添加多边形
     *
     * @param map        略
     * @param lonStrArr  ；
     * @param latStrArr；
     * @param name       同上
     * @param user       同上
     * @param type       同上
     * @return 同上
     */
    @ResponseBody
    @RequestMapping(value = "addpol.do", method = RequestMethod.POST)
    public String addPolygon2(ModelMap map, @RequestParam(value = "lonStrArr") String lonStrArr,
                              @RequestParam(value = "latStrArr") String latStrArr,
                              @RequestParam(value = "name", required = false) String name,
                              @RequestParam(value = "user", required = false) String user,
                              @RequestParam(value = "type", required = false) int type) {

        String msg;
        String jsonStr;
        try {
            String[] lonArr = SplitUtils.MDVNumSplit_StrArray(lonStrArr);
            String[] latArr = SplitUtils.MDVNumSplit_StrArray(latStrArr);
            if (lonArr.length != latArr.length) {
                msg = "多边形区域设置命令发送失败，错误代码：1";
                map.addAttribute("result", msg);
                jsonStr = StateMsg.toJson(-2, map);
                return jsonStr;
            } else {
                Point[] points = new Point[lonArr.length];
                for (int i = 0; i < lonArr.length; i++) {
                    Point p1 = new Point(Double.parseDouble(lonArr[i]), Double.parseDouble(latArr[i]));
                    points[i] = p1;
                }

                int id = addService.addPolygon(points, name, user, type);
                if (id < 0) {
                    map.addAttribute("error", "创建失败");
                    return StateMsg.toJson(id, map);
                }
                //300表示只存在自定义区域，id无用
                if (type == 300) {
                    id = 0;
                }
                map.addAttribute("id", id);
                return StateMsg.toJson(1, map);
            }
        } catch (Exception e) {
            msg = "多边形区域设置命令发送失败，错误代码：2";
            map.addAttribute("result", msg);
            jsonStr = StateMsg.toJson(-2, map);
            return jsonStr;
        }
    }

    private int addPolygon2(String lonStrArr, String latStrArr, String name, String user, int type) {
        try {
            String[] lonArr = SplitUtils.MDVNumSplit_StrArray(lonStrArr);
            String[] latArr = SplitUtils.MDVNumSplit_StrArray(latStrArr);
            Point[] points = new Point[lonArr.length];
            for (int i = 0; i < lonArr.length; i++) {
                Point p1 = new Point(Double.parseDouble(lonArr[i]), Double.parseDouble(latArr[i]));
                points[i] = p1;
            }
            return addService.addPolygon(points, name, user, type);
        } catch (Exception e) {
            return 0;
        }

    }

    /**
     * 添加圆形
     *
     * @param map    略
     * @param lon    圆心（double）
     * @param lat    圆心（double）
     * @param radius 半径（米）
     * @param name   同上
     * @param user   同上
     * @param type   同上
     * @return 同上
     */
    @ResponseBody
    @RequestMapping(value = "addcir.do", method = RequestMethod.POST)
    public String addCircle(ModelMap map, @RequestParam(value = "lon") double lon,
                            @RequestParam(value = "lat") double lat,
                            @RequestParam(value = "radius") int radius,
                            @RequestParam(value = "name", required = false) String name,
                            @RequestParam(value = "user", required = false) String user,
                            @RequestParam(value = "type", required = false) int type) {
        Point point = new Point(lon, lat);
        int id = addService.addCircle(point, radius, name, user, type);
        if (id < 0) {
            map.addAttribute("error", "创建失败");
            return StateMsg.toJson(id, map);
        }
        if (type == 300) {
            id = 0;
        }
        map.addAttribute("id", id);
        return StateMsg.toJson(1, map);
    }

    private int addCircle(double lon, double lat, int radius, String name, String user, int type) {
        Point point = new Point(lon, lat);
        return addService.addCircle(point, radius, name, user, type);
    }

    /**
     * 添加扇形区域
     *
     * @param map
     * @param lon
     * @param lat
     * @param radius
     * @param radsmal
     * @param start_deg
     * @param end_deg
     * @param name
     * @param user
     * @param type
     * @return
     */

    @ResponseBody
    @RequestMapping(value = "addsector.do", method = RequestMethod.POST)
    public String addSector(ModelMap map, @RequestParam(value = "lon") double lon,
                            @RequestParam(value = "lat") double lat,
                            @RequestParam(value = "radius") int radius,
                            @RequestParam(value = "radsmal") int radsmal,
                            @RequestParam(value = "start_deg") double start_deg,
                            @RequestParam(value = "end_deg") double end_deg,
                            @RequestParam(value = "name", required = false) String name,
                            @RequestParam(value = "user", required = false) String user,
                            @RequestParam(value = "type", required = false) int type) {
        Point point = new Point(lon, lat);
        int id = addService.addSector(point, radius, radsmal, start_deg, end_deg, name, user, type);
        if (type == 300) {
            id = 0;
        }
        map.addAttribute("id", id);
        return StateMsg.toJson(1, map);
    }

    private int addSector(double lon, double lat, int radius, int radsmal, double start_deg, double end_deg, String name, String user, int type) {
        Point point = new Point(lon, lat);
        return addService.addSector(point, radius, radsmal, start_deg, end_deg, name, user, type);
    }

    /**
     * 根据类型获取相应区域(停用)
     * @param map 略
     * @param type 获取区域类型：0：异常监控敏感区域；1：分发区域；2：其他区域（待定义）；255：全部区域
     * @return 区域列表
     *//*
    @ResponseBody
    @RequestMapping(value = "getareas.do",method = RequestMethod.POST)
    public String getAllArea(ModelMap map,
                             @RequestParam(value = "type",required = false) int type){
        List<Area> areas=opeService.getAllArea(type);
        map.addAttribute("arealist",areas);
        return StateMsg.toJson(1,map);
    }*/

    /**
     * 根据类型获取相应矩形(停用)
     * @param map 略
     * @param type 获取区域类型：0：异常监控敏感区域；1：分发区域；2：其他区域（待定义）
     * @return 区域列表
     *//*
    @ResponseBody
    @RequestMapping(value = "getrecs.do",method = RequestMethod.POST)
    public String getRectangles(ModelMap map,
                             @RequestParam(value = "type",required = false) int type){
        List<Rectangle> areas=opeService.getRectangles(type);
        map.addAttribute("arealist",areas);
        return StateMsg.toJson(1,map);
    }

    *//**
     * 根据类型获取相应多边形区域（停用）
     * @param map 略
     * @param type 获取区域类型：0：异常监控敏感区域；1：分发区域；2：其他区域（待定义）
     * @return 区域列表
     *//*
    @ResponseBody
    @RequestMapping(value = "getpols.do",method = RequestMethod.POST)
    public String getPolygons(ModelMap map,
                              @RequestParam(value = "type",required = false) int type){
        List<Polygon> areas=opeService.getPolygons(type);
        map.addAttribute("arealist",areas);
        return StateMsg.toJson(1,map);
    }

    *//**
     * 根据类型获取相应圆形区域（停用）
     * @param map 略
     * @param type 获取区域类型：0：异常监控敏感区域；1：分发区域；2：其他区域（待定义）
     * @return 区域列表
     *//*
    @ResponseBody
    @RequestMapping(value = "getcirs.do",method = RequestMethod.POST)
    public String getCircles(ModelMap map,
                             @RequestParam(value = "type",required = false) int type){
        List<Circle> areas=opeService.getCircles(type);
        map.addAttribute("arealist",areas);
        return StateMsg.toJson(1,map);
    }*/

    /**
     * 获取单一区域
     *
     * @param map 略
     * @param id  区域id
     * @return 单一区域
     */
    @ResponseBody
    @RequestMapping(value = "getarea.do", method = RequestMethod.POST)
    public String getArea(ModelMap map,
                          @RequestParam(value = "id", required = false) int id,
                          @RequestParam(value = "type", required = false) int type,
                          @RequestParam(value = "show_status", required = false) int show_status

    ) {

        Area area = opeService.getArea(id, type);
        if (show_status == 1) {
            map.addAttribute("area", changeGeo(area));
        } else if (show_status == 2) {
            map.addAttribute("area", area);
        }
        return StateMsg.toJson(1, map);
    }

    /**
     * 将之前Area类型转换为GeoJson
     * @param area
     * @return
     */
    public GeoDto changeGeo(Area area) {
        int shape = area.getShape();
        GeoDto dto = new GeoDto();
        double[][] coordinates;

        dto.setType("Feature");
        switch (shape) {
            case 1:
                //圆形
                coordinates = new double[1][2];
                coordinates[0][0] = area.getCentreLon() / 600000.0;
                coordinates[0][1] = area.getCentreLat() / 600000.0;

                dto.setGeometry(new GeoDto.Geometry("Circular", coordinates));
                dto.setProperties(new CircularGeoDto.Properties(area.getId(), area.getName(), area.getShape(), area.getStatus(), area.getRadius()));
                break;
            case 2:
                //矩形
                coordinates = new double[2][2];
                coordinates[0][0] = area.getLdlon() / 600000.0;
                coordinates[0][1] = area.getLdlat() / 600000.0;
                coordinates[1][0] = area.getRulon() / 600000.0;
                coordinates[1][1] = area.getRulat() / 600000.0;

                dto.setGeometry(new GeoDto.Geometry("Rectangle", coordinates));
                dto.setProperties(new GeoDto.Properties(area.getId(), area.getName(), area.getShape(), area.getStatus()));
                break;
            case 3:
                //多边形
                String polygonStr = area.getArea();
                String polygon = polygonStr.split("\\(\\(")[1].split("\\)\\)")[0];
                int size = polygon.split(",").length;

                coordinates = new double[size][2];

                int id = 0;
                for (String point : polygon.split(",")) {
                    coordinates[id][0] = Integer.parseInt(point.split(" ")[0]) / 600000.0;
                    coordinates[id][1] = Integer.parseInt(point.split(" ")[1]) / 600000.0;
                    id++;
                }
                dto.setGeometry(new GeoDto.Geometry("Polygon", coordinates));
                dto.setProperties(new GeoDto.Properties(area.getId(), area.getName(), area.getShape(), area.getStatus()));
                break;
            case 4:
                //扇形
                coordinates = new double[1][2];
                coordinates[0][0] = area.getCentreLon() / 600000.0;
                coordinates[0][1] = area.getCentreLat() / 600000.0;

                dto.setGeometry(new GeoDto.Geometry("Sector", coordinates));
                dto.setProperties(new SectorGeoDto.Properties(area.getId(), area.getName(), area.getShape(), area.getStatus(), area.getRadius(), area.getRadsmal(), area.getStart_deg(), area.getEnd_deg()));
                break;
        }
        return dto;
    }

    /**
     * 分页显示区域列表
     *
     * @param map
     * @param type
     * @param pageid
     * @param pagecount
     * @param show_status
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "getareapaging.do", method = RequestMethod.POST)
    public String getAreas(ModelMap map,
                           @RequestParam(value = "type", required = false) int type,
                           @RequestParam(value = "pageid", required = false) int pageid,
                           @RequestParam(value = "pagecount", required = false) int pagecount,
                           @RequestParam(value = "show_status", required = false) int show_status) {
        String jsonStr;

        List<Area> areas = opeService.getAreaPaging(type, pageid, pagecount);
        int count = opeService.getAreaCount(type);


        //计算最大页码
        int maxPage = PageUtils.getMaxPage(count, pagecount);
        map.addAttribute("total", count);
        map.addAttribute("max_page", maxPage);

        //根据要求显示不同的格式
        if (show_status == 1) {
            List<GeoDto> geoDtos = new ArrayList<GeoDto>();
            for (Area area : areas) {
                geoDtos.add(changeGeo(area));
            }
            map.addAttribute("areas", geoDtos);
        }
        if (show_status == 2) {
            map.addAttribute("areas", areas);
        }

        jsonStr = StateMsg.toJson(1, map);
        return jsonStr;


    }

    /**
     * 删除区域
     *
     * @param map 略
     * @param id  区域id
     * @return 单一区域
     */
    @ResponseBody
    @RequestMapping(value = "delarea.do", method = RequestMethod.POST)
    public String delArea(ModelMap map,
                          @RequestParam(value = "id", required = false) int id,
                          @RequestParam(value = "type", required = false) int type) {
        if (opeService.delArea(id, type)) {
            map.addAttribute("status", "success");
        } else {
            map.addAttribute("status", "error");
            return StateMsg.toJson(-1, map);
        }
        return StateMsg.toJson(1, map);
    }

    /**
     * 添加带预警区域的区域添加。输入区域，默认最多处理2个区域
     */
    @ResponseBody
    @RequestMapping(value = "setareapro.do", method = RequestMethod.POST)
    public String areaSet(ModelMap map, @RequestParam(value = "ldlon", required = false) double ldlon,
                                @RequestParam(value = "ldlat", required = false) double ldlat,
                                @RequestParam(value = "rulon", required = false) double rulon,
                                @RequestParam(value = "rulat", required = false) double rulat,
                                @RequestParam(value = "lonStrArr", required = false) String lonStrArr,
                                @RequestParam(value = "latStrArr", required = false) String latStrArr,
                                @RequestParam(value = "cirlon", required = false) double cirlon,
                                @RequestParam(value = "cirlat", required = false) double cirlat,
                                @RequestParam(value = "radius", required = false) int radius,
                                @RequestParam(value = "radsmal", required = false) int radsmal,
                                @RequestParam(value = "start_deg", required = false) double start_deg,
                                @RequestParam(value = "end_deg", required = false) double end_deg,
                                @RequestParam(value = "shape", required = false) int shape,
                                @RequestParam(value = "warning", required = false) int warning,
                                @RequestParam(value = "warning_lonStrArr", required = false) String warning_lonStrArr,
                                @RequestParam(value = "warning_latStrArr", required = false) String warning_latStrArr,
                                @RequestParam(value = "type", required = false) int type,
                                @RequestParam(value = "distance", required = false) double distance,
                                @RequestParam(value = "areaName", required = false) String areaName,
                                @RequestParam(value = "user", required = false) String user) {
        String msg;
        String jsonStr;

        //判断图形进行存储，如果是敏感区域，设置异常，根据图形不同，调用不同存储
        //敏感区域的id。
        int id=0;
        switch (shape) {
            case 1:
                id = addRectangle(ldlon, ldlat, rulon, rulat,
                        areaName,
                        user,
                        type);
                //异常区域，需要发PB
                if (type == 0 && id > 0) {
                    AreaSet areaSet = new AreaSet(ldlon, ldlat, rulon, rulat, areaName, id);
                    abnormalService.areaAbnormalSetRectangle(areaSet);
                }
                break;
            case 2:
                id = addCircle(cirlon, cirlat, radius, areaName, user, type);
                //异常区域，需要发PB
                if (type == 0 && id > 0) {
                    Point p1 = new Point(cirlon, cirlat);
                    abnormalService.areaAbnormalSetCircle(p1, radius, areaName, id);
                }
                break;
            case 3:
                id = addPolygon2(lonStrArr, latStrArr, areaName, user, type);
                //异常区域，需要发PB
                if (type == 0 && id > 0) {
                    try {
                        String[] lonArr = SplitUtils.MDVNumSplit_StrArray(lonStrArr);
                        String[] latArr = SplitUtils.MDVNumSplit_StrArray(latStrArr);
                        Point[] points = new Point[lonArr.length];
                        for (int j = 0; j < lonArr.length; j++) {
                            Point p1 = new Point(Double.parseDouble(lonArr[j]), Double.parseDouble(latArr[j]));
                            points[j] = p1;
                        }
                        abnormalService.areaAbnormalSetPolygons(points, areaName, id);
                    } catch (Exception e) {
                        msg = "异常设置命令发送失败";
                        map.addAttribute("result", msg);
                        jsonStr = StateMsg.toJson(-2, map);
                        return jsonStr;
                    }
                }
                break;
            case 4:
                id = addSector(cirlon,cirlat, radius, radsmal, start_deg, end_deg, areaName, user, type);
                //异常区域，需要发PB 扇形没有实现异常PB
                if (type == 0 && id > 0) {
                    Point p1 = new Point(cirlon, cirlat);
                    abnormalService.areaAbnormalSetSector(p1,radius,radsmal,start_deg,end_deg,areaName,id);
                }
                break;
        }


        //缓冲区域的名称
        String name="DO:" + id + ";" + "AN:" + areaName + ";" + "D:" + distance;

        //存在缓存区
        int warning_id=0;
        if(warning>0){
            warning_id = addPolygon2(warning_lonStrArr, warning_latStrArr, name, user, 3);
            //异常区域，需要发PB
            if (type == 0 && warning_id > 0) {
                try {
                    String[] lonArr = SplitUtils.MDVNumSplit_StrArray(warning_lonStrArr);
                    String[] latArr = SplitUtils.MDVNumSplit_StrArray(warning_latStrArr);
                    Point[] points = new Point[lonArr.length];
                    for (int j = 0; j < lonArr.length; j++) {
                        Point p1 = new Point(Double.parseDouble(lonArr[j]), Double.parseDouble(latArr[j]));
                        points[j] = p1;
                    }
                    abnormalService.areaAbnormalSetPolygons(points, name, warning_id);
                } catch (Exception e) {
                    msg = "缓冲区异常设置命令发送失败";
                    map.addAttribute("result", msg);
                    jsonStr = StateMsg.toJson(-2, map);
                    return jsonStr;
                }
            }
        }
        map.addAttribute("id", id);
        map.addAttribute("warning_id",warning_id);
        return StateMsg.toJson(1, map);
    }


}


